package com.esdk.utils;

import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.esdk.esdk;
import com.esdk.sql.orm.ABRowSet;
import com.esdk.sql.orm.IReadRowSet;
import com.esdk.sql.orm.IResultSet;
import com.esdk.sql.orm.IRow;
import lombok.NonNull;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class EasyExcel{
	public static byte[] toXls(@NonNull Object[][] arr2){
		try{
			String templet=EasyFile.loadFromFile(EasyFile.getInputStreamFromResources("com/esdk/utils/export.html"),Constant.UTF8);
			StringBuffer content=new StringBuffer();
			if(arr2==null)
				return new byte[0];
			for(int i=0;i<arr2.length;i++){
				content.append("<tr>");
				for(int j=0;j<arr2[i].length;j++){
					Object val=arr2[i][j];
					String tdTag=esdk.math.isNumeric(val) && !esdk.sql.isSnowId(val)?"<td x:num>":"<td>";
					content.append(tdTag).append(EasyStr.getStringNoNull(val)).append("</td>");
				}
				content.append("</tr>\n");
			}
			return templet.replace("${content}",content).getBytes("utf8");
		}catch(IOException e){
			throw esdk.tool.wrapThrowble(e);
		}
	}

	public static void toXls(@NonNull Object[][] arr2,@NonNull OutputStream os) throws IOException{
		try{
			String templet=EasyFile.loadFromFile(EasyFile.getInputStreamFromResources("com/esdk/utils/export.html"),Constant.UTF8);
			StringBuilder content=new StringBuilder();
			if(arr2==null)
				return;
			fillContent(os,templet,content,arr2);
		}catch(IOException e){
			throw esdk.tool.wrapThrowble(e);
		}
	}

	public static void toXls(@NonNull IReadRowSet<IRow> rs,@NonNull OutputStream os){
		toXls(rs,os,null,null);
	}

	public static void toXls(@NonNull IReadRowSet<IRow> rs,@NonNull OutputStream os,Map<String,String> chnColumsMap){
		toXls(rs,os,null,chnColumsMap);
	}
	/**
	 * @param chnColumsMap 字段名称转换成中文，如果找不到就用英文
	 * */
	public static void toXls(@NonNull IResultSet<IRow> rs,@NonNull OutputStream os,String[] columns,Map<String,String> chnColumsMap){
		try{
			String templet=EasyFile.loadFromFile(EasyFile.getInputStreamFromResources("com/esdk/utils/export.html"),Constant.UTF8);
			String[] cols=esdk.array.isValid(columns)?esdk.array.overlap(columns,rs.getColumns()):rs.getColumns();
			StringBuilder content=new StringBuilder();
			Object[][] arr2=rs.toArray2(true,cols);
			Object[] header=arr2[0];
			for(int i=0;i<header.length;i++){
				String engColName=(String)header[i];
				String chnColName=esdk.obj.IFNotnull(chnColumsMap,(e)->e.getOrDefault(engColName,engColName),engColName);
				header[i]=chnColName;
			}
			fillContent(os,templet,content,arr2);
		}catch(IOException e){
			throw esdk.tool.wrapThrowble(e);
		}
	}

	private static void fillContent(@NonNull OutputStream os,String templet,StringBuilder content,Object[][] arr2) throws IOException{
    for(Object[] objects: arr2){
      content.append("<tr>");
      for(int j=0;j<objects.length;j++){
        Object val=objects[j];
        String tdTag=esdk.math.isNumeric(val)&&!esdk.sql.isSnowId(val)?"<td x:num>":"<td>";
        content.append(tdTag).append(EasyStr.getStringNoNull(val)).append("</td>");
      }
      content.append("</tr>\n");
    }
		os.write(templet.replace("${content}",content).getBytes("utf8"));
	}


	public static <OS extends OutputStream> OS toXlsx(@NonNull IResultSet<IRow> rs,@NonNull OS os){
		return toXlsx(rs,os,null,null,0);
	}

	public static <OS extends OutputStream> OS toXlsx(@NonNull IResultSet<IRow> rs,@NonNull OS os,Map<String,String> chnColumsMap){
		return toXlsx(rs,os,null,chnColumsMap,null);
	}

	public static <OS extends OutputStream> OS toXlsx(@NonNull IResultSet<IRow> rs,@NonNull OS os,String[] columns){
		return toXlsx(rs,os,columns,null,null);
	}

	/**
	 * @param chnColumsMap 字段名称转换成中文，如果找不到就用英文
	 * */
	public static <OS extends OutputStream> OS toXlsx(@NonNull IResultSet<IRow> rs,@NonNull OS os,String[] columns,Map<String,String> chnColumsMap,Integer limit){
		ExcelWriterBuilder writerBuilder = com.alibaba.excel.EasyExcel.write(os);
		String sheetName="数据导出";
		String[] cols=esdk.array.isValid(columns)?esdk.array.overlap(columns,rs.getColumns()):rs.getColumns();
		List<List> dataList=rs.toList2(false,cols);
		for(int i=0;i<cols.length;i++){
			String col=cols[i];
			cols[i]=esdk.obj.IFNotnull(chnColumsMap,(e)->e.getOrDefault(col,col),col);
			if(limit!=null&&limit>=0&&i>limit){
				sheetName+="(已限制"+limit+"条记录)";
				break;
			}
		}
		dataList.add(0,Arrays.asList(cols));
		ExcelWriterSheetBuilder sheetBuilder = writerBuilder.sheet(sheetName).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy());
		sheetBuilder.doWrite(dataList);
		return os;
	}

	public static boolean toXls(@NonNull Object[][] arr2,@NonNull File out) throws IOException{
		return EasyFile.saveToFile(toXls(esdk.str.toArray2(arr2)),out,true);
	}

	public static void main(String[] args) throws IOException{
		esdk.sout(toXls(new String[][]{{"code","name"},{"A111","张三丰"},{"A222","李四光"}},new File("/output.xls")));
		ABRowSet rs=new ABRowSet("code","name","age","birthday");
		rs.append().put("code","A001").put("name","张三丰").put("age",18).put("birthday",esdk.time.toLocalDate("1998-01-01"));
		rs.append().put("code","A002").put("name","李四光").put("age",23).put("birthday",esdk.time.toLocalDateTime("2008-12-31T12:25:50"));
		Map map=Map.of("code","代码","name","姓名","age","年龄");
		toXls(rs,new FileOutputStream("/output1.xls"),map);
		toXlsx(rs,new FileOutputStream("/output2.xlsx"),map);
	}
}
